步驟 8:新增自訂命令與產生檔案

假設,為了本教學的目的,我們決定永遠不使用平台的 logexp 函數,而是想要產生一個預先計算值的表格,以在 mysqrt 函數中使用。在本節中,我們將在建置過程中建立此表格,然後將該表格編譯到我們的應用程式中。

首先,讓我們移除 MathFunctions/CMakeLists.txt 中對於 logexp 函數的檢查。然後從 mysqrt.cxx 中移除對於 HAVE_LOGHAVE_EXP 的檢查。同時,我們可以移除 #include <cmath>

MathFunctions 子目錄中,已提供一個名為 MakeTable.cxx 的新原始碼檔案,用於產生表格。

在檢閱檔案後,我們可以發現該表格是以有效的 C++ 程式碼產生的,並且輸出檔案名稱是以引數形式傳入的。

下一步是建立 MathFunctions/MakeTable.cmake。然後,將適當的命令新增到檔案中,以建置 MakeTable 可執行檔,然後在建置過程中執行它。需要幾個命令才能完成此操作。

首先,我們為 MakeTable 新增一個可執行檔。

MathFunctions/MakeTable.cmake
add_executable(MakeTable MakeTable.cxx)

建立可執行檔後,我們使用 target_link_libraries()tutorial_compiler_flags 新增到我們的可執行檔。

然後我們新增一個自訂命令,指定如何透過執行 MakeTable 來產生 Table.h

MathFunctions/MakeTable.cmake
add_custom_command(
  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
  COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
  DEPENDS MakeTable
  )

接下來,我們必須讓 CMake 知道 mysqrt.cxx 依賴於產生的檔案 Table.h。這是透過將產生的 Table.h 新增到程式庫 SqrtLibrary 的來源列表來完成的。

MathFunctions/CMakeLists.txt
  add_library(SqrtLibrary STATIC
              mysqrt.cxx
              ${CMAKE_CURRENT_BINARY_DIR}/Table.h
              )

我們還必須將目前的二進制目錄新增到包含目錄列表中,以便 Table.h 可以被找到並被 mysqrt.cxx 包含。

MathFunctions/CMakeLists.txt
  target_include_directories(SqrtLibrary PRIVATE
                             ${CMAKE_CURRENT_BINARY_DIR}
                             )

  # link SqrtLibrary to tutorial_compiler_flags

作為最後一步,我們需要在 MathFunctions/CMakeLists.txt 的頂部包含 MakeTable.cmake

MathFunctions/CMakeLists.txt
  include(MakeTable.cmake)

現在讓我們使用產生的表格。首先,修改 mysqrt.cxx 以包含 Table.h。接下來,我們可以重寫 mysqrt 函數以使用表格

MathFunctions/mysqrt.cxx
double mysqrt(double x)
{
  if (x <= 0) {
    return 0;
  }

  // use the table to help find an initial value
  double result = x;
  if (x >= 1 && x < 10) {
    std::cout << "Use the table to help find an initial value " << std::endl;
    result = sqrtTable[static_cast<int>(x)];
  }

  // do ten iterations
  for (int i = 0; i < 10; ++i) {
    if (result <= 0) {
      result = 0.1;
    }
    double delta = x - (result * result);
    result = result + 0.5 * delta / result;
    std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
  }

  return result;
}
}
}

執行 cmake 可執行檔或 cmake-gui 來設定專案,然後使用您選擇的建置工具來建置它。

當這個專案被建置時,它會先建置 MakeTable 可執行檔。然後它會執行 MakeTable 以產生 Table.h。最後,它將編譯包含 Table.hmysqrt.cxx,以產生 MathFunctions 程式庫。

執行 Tutorial 可執行檔並驗證它正在使用表格。